#ifndef __CCIRCLE_H__
#define __CCIRCLE_H__

#include "StdDefs.h"
#include "CMathFixed.h"
#include "CVector2d.h"
#include "CLineSegment2d.h"
#include "CSpace.h"

 


class CCircle
{
public:
	enum CollisionResolution {
		Stop,
		Slide,
		Bounce
	};


public:
	CCircle(){}
	CCircle( fixed i, fixed j,fixed rad );
	CCircle( const CVector2d& translation, fixed rad );
	CCircle( const CCircle& s );
	~CCircle(){}


	static boolean		Intersects( const CVector2d& translation, fixed radiusSquared,
									const CLineSegment2d& l, 
									CVector2d& closestPoint, 
									CSpace::Relativity* relativity = NULL );

	static boolean		Intersects( const CVector2d& translation, fixed radius, fixed radiusSquared,
									const CVector2d& nextTranslation,
									const CLineSegment2d& l,
									fixed& u );

	//static boolean		Intersects( const CVector2d& translation, fixed radius,
	//								const CVector2d& direction, fixed speed,
	//								const CLineSegment2d& l,
	//								fixed& u );

	static boolean		DetectAndResolveCollision( const CVector2d& translation, fixed radius, fixed radiusSquared,
												   const CLineSegment2d& l,
												   CVector2d& newTranslation, fixed& u,
												   CollisionResolution resolution = Stop,
												   const CVector2d* lNormalPreComputed = NULL );

	static boolean		DetectAndResolveCollisionConvextArea( const CVector2d& translation, fixed radius,
															  const CVector2d* vtx, int32 nOfVertices,
															  CVector2d& newTranslation,
															  CollisionResolution resolution = Stop,
															  const CVector2d* lNormalPreComputed = NULL );

	static boolean		ContainInsideConvexArea( const CVector2d& translation, fixed radius,
												 const CVector2d* vtx, int32 nOfVertices,
												 CVector2d& newTranslation ); 

	//todo:
	//static boolean		ContainOutsideConvexArea( const CVector2d& translation, fixed radius,
	//											  const CVector2d* vtx, int32 nOfVertices,
	//											  CVector2d& newTranslation ); 

	CCircle&			Set( fixed i, fixed j, fixed rad );
	CCircle&			Set( const CVector2d& translation, fixed rad );

	boolean				Intersects( const CLineSegment2d& l, 
									CVector2d& closestPoint, 
									CSpace::Relativity* relativity ) const;

	boolean				Intersects( const CVector2d& nextTranslation,
									const CLineSegment2d& l,
									fixed& u ) const;

	boolean				Intersects( fixed radiusSquared, const CVector2d& nextTranslation,
									const CLineSegment2d& l,
									fixed& u ) const;

	//boolean				Intersects( const CVector2d& direction, fixed speed, 
	//								const CLineSegment2d& l,
	//								fixed& u ) const;

	boolean				DetectAndResolveCollision( const CLineSegment2d& l,
												   CVector2d& newTranslation, fixed& u,
												   CollisionResolution resolution = Stop,
												   const CVector2d* lNormalPreComputed = NULL ) const;

	boolean				DetectAndResolveCollision( fixed radiusSquared,
												   const CLineSegment2d& l,
												   CVector2d& newTranslation, fixed& u,
												   CollisionResolution resolution = Stop,
												   const CVector2d* lNormalPreComputed = NULL ) const;

	boolean				DetectAndResolveCollisionConvextArea( const CVector2d* vtx, int32 nOfVertices,
															  CVector2d& newTranslation,
															  CollisionResolution resolution = Stop,
															  const CVector2d* lNormalPreComputed = NULL ) const;

	boolean				ContainInsideConvexArea( const CVector2d* vtx, int32 nOfVertices,
												 CVector2d& newTranslation ) const;

	//todo:
	//boolean				ContainOutsideConvexArea( const CVector2d* vtx, int32 nOfVertices,
	//											  CVector2d& newTranslation,
	//											  CVector2d* vtxNormal,
	//											  boolean vtxNormalsAreValid = FALSE ) const;

	fixed				m_radius;
	CVector2d			m_translation;
};




inline 
CCircle::CCircle( fixed i, fixed j, fixed rad )
{ 
	m_radius = rad;
	m_translation.Set( i, j ); 
}


inline
CCircle::CCircle( const CVector2d& translation, fixed rad )
{
	m_radius = rad; 
	m_translation = translation;
}


inline 
CCircle::CCircle( const CCircle& s )
{
	m_radius = s.m_radius; 
	m_translation = s.m_translation;
}


inline 
CCircle& CCircle::Set( fixed i, fixed j, fixed rad )
{ 
	m_radius = rad;
	m_translation.Set( i, j );

	return *this;
}


inline
CCircle& CCircle::Set( const CVector2d& translation, fixed rad )
{
	m_radius = rad; 
	m_translation = translation;

	return *this;
}


inline
boolean	CCircle::Intersects( const CLineSegment2d& l, 
							 CVector2d& closestPoint, 
							 CSpace::Relativity* relativity ) const
{
	return Intersects( m_translation, CMathFixed::Mul( m_radius, m_radius ), 
					   l, closestPoint, relativity );
}


inline
boolean	CCircle::Intersects( const CVector2d& nextTranslation,
							 const CLineSegment2d& l,
							 fixed& u ) const
{
	return Intersects( CMathFixed::Mul( m_radius, m_radius ), nextTranslation, l, u );	
}


inline
boolean	CCircle::Intersects( fixed radiusSquared, const CVector2d& nextTranslation,
							 const CLineSegment2d& l,
							 fixed& u ) const
{
	return Intersects( m_translation, m_radius, radiusSquared, nextTranslation, l, u );	
}


//inline
//boolean CCircle::Intersects( const CVector2d& direction, fixed speed,
//							 const CLineSegment2d& l,
//							 fixed& u ) const
//{
//	return Intersects( m_translation, m_radius, direction, speed, l, u );
//}


inline
boolean	CCircle::DetectAndResolveCollision( const CLineSegment2d& l,
											CVector2d& newTranslation, fixed& u,
											CollisionResolution resolution,
											const CVector2d* lNormalPreComputed ) const
{
	return DetectAndResolveCollision( CMathFixed::Mul( m_radius, m_radius ), l, newTranslation, u,
									  resolution, lNormalPreComputed );
}


inline
boolean	CCircle::DetectAndResolveCollision( fixed radiusSquared,
											const CLineSegment2d& l,
											CVector2d& newTranslation, fixed& u,
											CollisionResolution resolution,
											const CVector2d* lNormalPreComputed ) const
{
	return DetectAndResolveCollision( m_translation, m_radius, radiusSquared, l, newTranslation, u,
									  resolution, lNormalPreComputed );	
}


inline
boolean	CCircle::DetectAndResolveCollisionConvextArea( const CVector2d* vtx, int32 nOfVertices,
													   CVector2d& newTranslation,
													   CollisionResolution resolution,
													   const CVector2d* lNormalPreComputed ) const
{
	return DetectAndResolveCollisionConvextArea( m_translation, m_radius, vtx, nOfVertices, newTranslation, 
												 resolution, lNormalPreComputed );
}


inline
boolean CCircle::ContainInsideConvexArea( const CVector2d* vtx, int32 nOfVertices,
										  CVector2d& newTranslation ) const
{
	return ContainInsideConvexArea( m_translation, m_radius, vtx, nOfVertices, newTranslation );
}



#endif // __CCIRCLE_H__